package com.lframework.jh.push.plugin.tx.sms;

import com.lframework.jh.push.core.exceptions.impl.DefaultClientException;
import com.lframework.jh.push.core.exceptions.impl.DefaultSysException;
import com.lframework.jh.push.core.exceptions.impl.InputErrorException;
import com.lframework.jh.push.core.utils.ArrayUtil;
import com.lframework.jh.push.core.utils.DateUtil;
import com.lframework.jh.push.core.utils.JsonUtil;
import com.lframework.jh.push.core.utils.StringUtil;
import com.lframework.jh.push.plugin.core.SmsPushChannel;
import com.lframework.jh.push.plugin.core.SmsPushChannelParams;
import com.lframework.jh.push.plugin.core.SmsPushResp;
import com.lframework.jh.push.plugin.core.constants.PushConstants;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultDetailDto;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultDetailRespDto;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultPageDto;
import com.lframework.jh.push.plugin.core.dto.QuerySmsPushResultPageRespDto;
import com.lframework.jh.push.plugin.core.enums.SmsQueryType;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.PullSmsSendStatus;
import com.tencentcloudapi.sms.v20210111.models.PullSmsSendStatusByPhoneNumberRequest;
import com.tencentcloudapi.sms.v20210111.models.PullSmsSendStatusByPhoneNumberResponse;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 文档地址 https://cloud.tencent.com/document/product/382/43194
 */
@Slf4j
@Component("tx_sms" + PushConstants.SMS_PUSH_CHANNEL_BEAN_NAME_SUFFIX)
public class TxSmsPushChannel implements SmsPushChannel {

    @Override
    public Class<? extends SmsPushChannelParams> getClazz() {
        return TxSmsPushChannelParams.class;
    }

    @Override
    public SmsPushResp push(SmsPushChannelParams params) throws Exception {

        TxSmsPushChannelParams channelParams = (TxSmsPushChannelParams) params;
        TxSmsExtra extra = JsonUtil.parseObject(channelParams.getExtra(), TxSmsExtra.class);

        SmsClient client = this.buildClient(params);
        SendSmsRequest req = new SendSmsRequest();
        req.setSmsSdkAppId(channelParams.getSdkAppId());

        req.setSignName(extra.getSignName());
        req.setTemplateId(extra.getTemplateCode());
        if (StringUtil.isNotBlank(extra.getTemplateParam())) {
            req.setTemplateParamSet(
                ArrayUtil.toArray(JsonUtil.parseList(extra.getTemplateParam(), String.class),
                    String.class));
        }

        req.setPhoneNumberSet(channelParams.getPhoneNumbers().split(","));

        TxSmsPushResp resp = new TxSmsPushResp();

        try {
            SendSmsResponse smsResp = client.SendSms(req);
            log.info("腾讯云短信发送 接口响应数据 {}", JsonUtil.toJsonStr(smsResp));
            List<TxSmsPushDetailResp> detailResps = new ArrayList<>();
            for (SendStatus sendStatus : smsResp.getSendStatusSet()) {
                TxSmsPushDetailResp detailResp = new TxSmsPushDetailResp();
                detailResp.setBizId(sendStatus.getSerialNo());
                detailResp.setChannelFlag("OK".equalsIgnoreCase(sendStatus.getCode()) ? 1 : 0);
                detailResp.setPhoneNumber(sendStatus.getPhoneNumber().replace("+86", ""));
                detailResp.setErrorMsg(
                    detailResp.getChannelFlag() == 0 ? sendStatus.getMessage() : null);

                detailResps.add(detailResp);
            }
            resp.setDetails(detailResps);
        } catch (TencentCloudSDKException e) {
            log.info("腾讯云短信发送失败，错误信息 {}", e.getMessage());
            throw new DefaultClientException(e.getMessage());
        }

        return resp;
    }

    @Override
    public QuerySmsPushResultDetailRespDto query(QuerySmsPushResultDetailDto dto) throws Exception {
        QuerySmsPushResultDetailRespDto respDto = null;
        try {
            respDto = this.query(1, dto); // 这里看文档发现offset固定是0
        } catch (DefaultClientException e) {
        }

        return respDto;
    }

    public QuerySmsPushResultDetailRespDto query(int pageIndex, QuerySmsPushResultDetailDto dto)
        throws Exception {
        TxSmsPushChannelParams channelParams = (TxSmsPushChannelParams) dto.getParams();

        SmsClient client = this.buildClient(dto.getParams());
        PullSmsSendStatusByPhoneNumberRequest req = new PullSmsSendStatusByPhoneNumberRequest();
        req.setBeginTime(DateUtil.toEpochMilli(dto.getPushTime()) / 1000L);
        req.setOffset((pageIndex - 1) * 100L);
        req.setLimit(100L);
        req.setPhoneNumber("+86" + dto.getPhoneNumber());
        req.setSmsSdkAppId(channelParams.getSdkAppId());

        PullSmsSendStatusByPhoneNumberResponse resp = client.PullSmsSendStatusByPhoneNumber(req);
        log.info("腾讯云短信查询 接口响应数据 {}", JsonUtil.toJsonStr(resp));
        if (ArrayUtil.isEmpty(resp.getPullSmsSendStatusSet())) {
            throw new DefaultClientException("没有分页数据");
        }
        for (PullSmsSendStatus pullSmsSendStatus : resp.getPullSmsSendStatusSet()) {
            if (!dto.getBizId().equals(pullSmsSendStatus.getSerialNo())) {
                continue;
            }
            QuerySmsPushResultDetailRespDto respDto = new QuerySmsPushResultDetailRespDto();
            respDto.setPhoneNumber(dto.getPhoneNumber());
            if ("SUCCESS".equalsIgnoreCase(pullSmsSendStatus.getReportStatus())) {
                respDto.setStatus(3);
                respDto.setSuccessTime(
                    DateUtil.of(pullSmsSendStatus.getUserReceiveTime() * 1000L,
                        ZoneId.systemDefault()));
            } else if ("FAIL".equalsIgnoreCase(pullSmsSendStatus.getReportStatus())) {
                respDto.setStatus(2);
                respDto.setErrorMsg(pullSmsSendStatus.getDescription());
            }

            return respDto;
        }

        return null;
    }

    @Override
    public QuerySmsPushResultPageRespDto query(QuerySmsPushResultPageDto dto) throws Exception {
        throw new DefaultSysException("不支持分页方式查询");
    }

    private SmsClient buildClient(SmsPushChannelParams params) {
        TxSmsPushChannelParams channelParams = (TxSmsPushChannelParams) params;
        Credential cred = new Credential(channelParams.getSecretId(), channelParams.getSecretKey());
        SmsClient client = new SmsClient(cred,
            StringUtil.isBlank(channelParams.getRegion()) ? "ap-guangzhou"
                : channelParams.getRegion());

        return client;
    }

    @Override
    public void validExtra(String extra) {
        if (StringUtil.isBlank(extra)) {
            throw new InputErrorException("extra不能为空！");
        }
        if (!JsonUtil.isJsonObject(extra)) {
            throw new InputErrorException("extra格式有误，应为JSON字符串！");
        }
        TxSmsExtra smsExtra = JsonUtil.parseObject(extra, TxSmsExtra.class);
        if (StringUtil.isBlank(smsExtra.getSignName())) {
            throw new InputErrorException("extra.signName不能为空！");
        }

        if (StringUtil.isBlank(smsExtra.getTemplateCode())) {
            throw new InputErrorException("extra.templateCode不能为空！");
        }

        if (StringUtil.isNotBlank(smsExtra.getTemplateParam())) {
            if (!JsonUtil.isJsonArray(smsExtra.getTemplateParam())) {
                throw new InputErrorException("extra.templateParam格式有误，应为JSON Array字符串！");
            }
        }
    }

    @Override
    public Integer allowSmsCount() {
        return 200;
    }

    @Override
    public SmsQueryType getQueryType() {
        return SmsQueryType.DETAIL;
    }
}
